package com.ten.config;

import com.alibaba.fastjson.JSON;
import com.ten.service.MyUserService;
import com.ten.common.core.util.JWTUtil;
import com.ten.common.core.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author ：Q大侠
 * @date ：Created in 2022/11/30 18:08
 * @description：登陆验证
 * @modified By：
 * @version:
 */
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private MyUserService userService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //设置登陆表单的规则
        http.formLogin()
                //登陆成功后执行的函数
                .successHandler(successHandler())
                //登陆失败后执行的函数
                .failureHandler(failureHandler())
                //放行前两者
                .permitAll();
        //设置sucurity允许登录跨域
        http.cors();
        //关闭跨域伪造请求
        http.csrf().disable();
        //其他所有请求都需要验证
        http.authorizeRequests().anyRequest().authenticated();
    }
//    @Override
//    public void configure(WebSecurity web) throws Exception {
//        web.ignoring().mvcMatchers("/doc.html");
//    }
    //登陆成功
    private AuthenticationSuccessHandler successHandler(){
        return (request, response, authentication) -> {
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();
            //生产token--userid+permission--JWT
            //获取登陆成功后用户对象
            User user = (User) authentication.getPrincipal();
            //登陆成功的账户
            String username = user.getUsername();
            //获取登陆账号的权限
            Collection<GrantedAuthority> authorities = user.getAuthorities();
            List<String> permissions = authorities.stream()
                    .filter(item->item.getAuthority()!=null)
                    .map(item->item.getAuthority())
                    .collect(Collectors.toList());
            ConcurrentHashMap<String,Object> map = new ConcurrentHashMap<>();
            map.put("username",username);
            map.put("premissions",permissions);
//            map.put("")
            //按照账户和权限生产token
            String token = JWTUtil.createJWT(map);
            //封装到响应对象之中
            Result result = new Result(2000, "登陆成功!", token);
            String jsonString = JSON.toJSONString(result);
            writer.print(jsonString);
            writer.flush();
            writer.close();
        };
    }
    //登陆失败
    private AuthenticationFailureHandler failureHandler(){
        return (request,response,e) -> {
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();
            Result result = new Result(5000, "账户或密码错误!");
            String jsonString = JSON.toJSONString(result);
            writer.print(jsonString);
            writer.flush();
            writer.close();
        };
    }
}
